#pragma once
/*
 * mysql connection.
 */
#include "type.h"
#include "mysql.h"
#include "mysql_db.h"
#include "thread.h"
#include "command_queue.h"


namespace SMysqlSpace {
	typedef MYSQL* mysqlHandle;
	class CMysqlRecordset;

	class CMysqlConnection : public IMysqlConnection, public CThread {
	public:
		CMysqlConnection();
		virtual ~CMysqlConnection();
		CMysqlConnection(const CMysqlConnection&) = delete;
		CMysqlConnection operator= (const CMysqlConnection&) = delete;
		enum reconnectError {
			CR_SERVER_LOST = 2013,
			CR_CONN_HOST_ERROR = 2003,
			CR_SERVER_GONE_ERROR = 2006,
		};

	public:
		// query with result: error, with result, without result.
		virtual int STDCALL QueryWithResult(const char* sql, IMysqlRecordset** ppoRes);

		// query without no result: error and affect lines.
		virtual int STDCALL QueryWithoutResult(const char* sql);

		// escape string, should assert(nFromLen >= (2 * nToLen + 1)), otherwise, return -1
		virtual int STDCALL EscapeString(const char* from, int fromLen, char* to, int toLen);

		// get last executing error
		virtual const char* STDCALL GetLastError();
		virtual int STDCALL GetLastErrorNo();

		// execute synchronize
		int STDCALL QueryWithResultSync(const char* sql, CMysqlRecordset* poRes);

	public:
		// thread virtual function
		virtual void run();
		virtual void stop();

	public:
		// connect mysql
		bool Connect(const char* ip, uint16 port,
			const char* name, const char* password,
			const char* db, const char* charset = "utf8"
		);
		bool Connect(const SConnectMysqlInfo& connectInfo);

		// reconnect mysql
		bool Reconnect();

		// close mysql.
		void Close();

		// add command
		void AddCommand(ICommand* poCommand, bool priority);

		// escape string
		template <uint32 N>
		inline int EscapeString(const char* from, int fromLen, char(&to)[N]) {
			return this->EscapeString(from, fromLen, to, N);
		}

		// release
		void Release();

	protected:
		bool connect();
		void doRelease();

	private:
		SConnectMysqlInfo m_connectInfo;
		mysqlHandle       m_mySQL{nullptr};
		CCommandQueue     m_commandQueue;
		bool              m_terminate{ false };
	};
}